/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mp.appApi.database;

import com.mp.appApi.util.XmlUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.dom4j.Document;
import org.dom4j.Element;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.jasypt.util.text.BasicTextEncryptor;

/**
 * @Date 130917
 * @author vannh
 */
public class HibernateUtils {

    private static Map<String, SessionFactory> sessionMap = new HashMap<String, SessionFactory>();
    private final static Object lock = new Object();

    private HibernateUtils() {
    }

    /*
     * Tao doi tuong singleton
     */
    private static class HibernateUtilHolder {

        public static final HibernateUtils INSTANCE = new HibernateUtils();
    }

    /*
     * Tra ve doi tuong singleton
     */
    public static HibernateUtils getInstance() {
        return HibernateUtilHolder.INSTANCE;
    }

    /*
     * Khoi tao du lieu cho hibernate util
     * configPath: duong dan den file config hibernate
     * salt: chuoi khoa ma hoa du lieu nhay cam
     */
    public void buildPool(String configPath, String salt) throws Exception {
        if (sessionMap.isEmpty()) {
            if (null == configPath || configPath.trim().isEmpty()) {
                throw new Exception("Error when initial data for hibernateUtil: configPath is empty !");
            } else if (salt == null || salt.isEmpty()) {
                throw new Exception("Error when initial data for hibernateUtil: salt is empty !");
            } else {
                configPath = configPath.trim();

                //
                try {
                    XmlUtils xml = new XmlUtils();
                    Document doc = xml.parse(configPath);
                    Element root = doc.getRootElement();
                    List<Element> elements = xml.getElementsByName(root, "DBInfo");

                    //khoi tao
                    for (Element e : elements) {
                        String name = xml.getValueElementByName(e, "name");
                        String path = xml.getValueElementByName(e, "path");

                        if (name == null || name.trim().isEmpty()) {
                            throw new Exception("Error when initial data for hibernateUtil: name is empty !");
                        } else if (path == null || path.trim().isEmpty()) {
                            throw new Exception("Error when initial data for hibernateUtil: path is empty !");
                        } else {
                            SessionFactory sessionFactory = createSessionFactory(path, salt);
                            sessionMap.put(name.trim().toLowerCase(), sessionFactory);
                        }
                    }
                } catch (Exception e) {
                    throw new Exception("Error when initial data for hibernateUtil !", e);
                }
            }
        } else {
            throw new Exception("Error when initial data for hibernateUtil: sessionFactoryMap initialed !");
        }
    }

    /*
     * Tao mot session factory
     */
    private SessionFactory createSessionFactory(String configPath, String salt) {
        SessionFactory sessionFactory;

        Configuration config = new Configuration();
        config.configure(configPath);
        BasicTextEncryptor textEn = new BasicTextEncryptor();
        textEn.setPassword(salt);

        //gia ma cac tham so dau vao
        String username = config.getProperty("hibernate.connection.username");
        String password = config.getProperty("hibernate.connection.password");
        String url = config.getProperty("hibernate.connection.url");
        username = textEn.decrypt(username);
        password = textEn.decrypt(password);
        url = textEn.decrypt(url);

        //set lai cac tham so vao cau hinh hibernate
        config.setProperty("hibernate.connection.username", username);
        config.setProperty("hibernate.connection.password", password);
        config.setProperty("hibernate.connection.url", url);

        //khoi tao sessionfactory
        sessionFactory = config.buildSessionFactory();

        return sessionFactory;
    }

    /*
     * Lay mot session voi shecma tuong ung
     */
    public Session getCurrentSession(String name) throws Exception {
        Session session;

        synchronized (lock) {
            if (name == null || name.trim().isEmpty()) {
                throw new Exception("Error when get current session: name is empty !");
            } else if (sessionMap.containsKey(name.trim().toLowerCase())) {
                session = sessionMap.get(name.trim().toLowerCase()).getCurrentSession();
                session.beginTransaction();
            } else {
                throw new Exception("Error when get current session: name not exist !");
            }
        }

        return session;
    }

    /*
     * Lay mot session voi shecma tuong ung
     */
    public Session openSession(String name) throws Exception {
        Session session;

        synchronized (lock) {
            if (name == null || name.trim().isEmpty()) {
                throw new Exception("Error when get current session: name is empty !");
            } else if (sessionMap.containsKey(name.trim().toLowerCase())) {
                session = sessionMap.get(name.trim().toLowerCase()).openSession();
            } else {
                throw new Exception("Error when get current session: name not exist !");
            }
        }

        return session;
    }
    
    /*
     * Kill all connection
     */
    public void releaseConnection(){
        if(sessionMap != null){
            for(Entry<String, SessionFactory> entry : sessionMap.entrySet()){
                if(!entry.getValue().isClosed()){
                    entry.getValue().close();
                }
            }
        }
    }
}
